import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;


public class Environment extends Data {
	private Environment parent;
	HashMap<String, Data> bindings;
	
	public Environment() {
		parent = null;
		bindings = new HashMap<String, Data>();
	}
	
	public Environment(Data variables, Data values, Environment env) {
		parent = env;
		bindings = new HashMap<String, Data>();
		if (Primitive.numCars(variables) <= Primitive.length(values)) {
			while (variables.isPair()) {
				this.makeAssignment(variables.car().toString(), values.car());
				variables = variables.cdr();
				values = values.cdr();
			}
			if (variables.isAtom()) {
				this.makeAssignment(variables.toString(), values);
			}
		} else {
			throw new SchavaException("Extending environment: mismatched arguments");
		}
	}
	
	
	public void makeAssignment(String variable, Data value) {
		bindings.put(variable, value);
	}
	
	public void setVariableValue(String variable, Data value) {
		if (bindings.containsKey(variable)) {
			bindings.put(variable, value);
		} else if (parent == null) {
			throw new SchavaException("Unbound variable: " + variable);
		} else {
			parent.setVariableValue(variable, value);
		}
	}
	
	public Data lookupVariable(String variable) {
		if (bindings.containsKey(variable)) {
			return bindings.get(variable);
		} else if (parent == null) {
			throw new SchavaException("Unbound variable: " + variable);
		} else {
			return parent.lookupVariable(variable);
		}
	}
	
	public void makeAssignments(LinkedList<Pair> pairs) {
		Iterator<Pair> assignmentPair = pairs.iterator();
		String name;
		Data value;
		while (assignmentPair.hasNext()) {
			Pair pair = assignmentPair.next();
			name = pair.car().toString();
			value = pair.cdr();
			this.makeAssignment(name, value);
		}
	}

	
	public String toString() {
		return "@env: " + this.hashCode();
	}

	@Override
	public int compareTo(Data o) {
		throw new SchavaException("Cannot compare environments");
	}

}
